﻿#include "Application.h"
#include "Input.h"

#include "glad/glad.h"
#include <GLFW/glfw3.h>
#include "Renderer/Renderer.h"
#include "Renderer/RenderCommand.h"

namespace ArsEngine {

	Application* Application::s_Instance = nullptr;

	Application::Application()
	{
		m_Window = Window::Create(WindowProps());
		m_Window->SetEventCallback(AN_BIND_EVENT_FN(Application::OnEvent));
	
	}

	void Application::Initialize()
	{
		m_ImGuiLayer = new ImGuiLayer();
		PushOverlayer(m_ImGuiLayer);
	}

	Application::~Application()
	{

	}

	void Application::OnEvent(Event& e)
	{
		EventDispatcher dispatcher(e);
		dispatcher.Dispatch<WindowCloseEvent>(AN_BIND_EVENT_FN(Application::OnWindowClose));

		//AN_CORE_INFO("{0}", e.ToString());

		for (auto it = m_LayerStack.rbegin(); it != m_LayerStack.rend(); ++it)
		{
			(*it)->OnEvent(e);

			if (e.Handled)
			{
				break;
			}
		}
	}

	bool Application::OnWindowClose(WindowCloseEvent& event)
	{
		m_Running = false;
		return true;
	}

	void Application::PushLayer(Layer* layer)
	{
		m_LayerStack.PushLayer(layer);
		layer->OnAttach();
	}

	void Application::PushOverlayer(Layer* overlay)
	{
		m_LayerStack.PushOverLayer(overlay);
		overlay->OnAttach();
	}

	void Application::StartApp()
	{
		if (!s_Instance)
		{
			s_Instance = new Application();
		}

	}

	void Application::Run()
	{
		while (m_Running)
		{
			float time = (float)glfwGetTime();
			TimeStep timestep = time - m_LastFrameTime;
			m_LastFrameTime = time;

			for (auto layer : m_LayerStack)
			{
				layer->OnUpdate(timestep);
			}

			m_ImGuiLayer->Begin();

			for (auto layer : m_LayerStack)
			{
				layer->OnImGuiRender();
			}

			m_ImGuiLayer->End();

			m_Window->OnUpdate();
		}
	}

	Application* Application::GetInstance()
	{
		if (!s_Instance)
		{
			return nullptr;
		}

		return s_Instance;
	}
}
